package controller

import (
	"fmt"
	"net/http"
	"time"

	"github.com/labstack/echo"

	"gopkg.in/mgo.v2/bson"

	"m-project-admin/app/entity"
	"m-project-admin/app/manager"
	"m-project-admin/app/model"
	"m-project-admin/app/utils"
	"strings"
)

// AddRole
func AddRole(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	// 查询App列表
	apps, _ := manager.GetAllAppList()
	appList := make([]interface{}, 0)
	for _, row := range apps {
		item := make(map[string]interface{})
		item["id"] = row.Id.Hex()
		item["app_name"] = row.App_name
		appList = append(appList, item)
	}

	data := make(map[string]interface{})
	data["loginAdminInfo"] = loginAdminInfo
	data["appList"] = appList
	data["env_desc"] = utils.GetEnvDesc()
	return c.Render(http.StatusOK, "add_role.html", data)
}

// do add role
func DoAddRole(c echo.Context) error {
	name := c.FormValue("name")
	if name == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写角色名称"})
	}

	desc := c.FormValue("desc")
	if desc == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写角色描述"})
	}

	appId := c.FormValue("app_id")
	if appId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择APP"})
	}

	role := model.Role{
		Id:          bson.NewObjectId(),
		Name:        name,
		Desc:        desc,
		App_id:      appId,
		Adminid:     manager.GetCurrentAdminId(&c),
		Create_time: time.Now().Unix(),
		Update_time: time.Now().Unix(),
	}

	_, err := manager.SaveRole(role)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// UpdateRole
func UpdateRole(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	id := c.QueryParam("id")
	if id == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞请选择要修改的角色😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	// 查询角色信息
	role, _ := manager.GetRoleById(id)
	if role.Id.Hex() == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞要修改的角色数据不存在😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	// 查询App列表
	apps, _ := manager.GetAllAppList()
	appList := make([]interface{}, 0)
	for _, row := range apps {
		item := make(map[string]interface{})
		item["id"] = row.Id.Hex()
		item["app_name"] = row.App_name
		appList = append(appList, item)
	}

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["roleInfo"] = formatRole(role)
	data["app_id"] = role.App_id
	data["appList"] = appList
	data["loginAdminInfo"] = loginAdminInfo
	data["env_desc"] = utils.GetEnvDesc()
	return c.Render(http.StatusOK, "update_role.html", data)
}

// DoUpdateRole
func DoUpdateRole(c echo.Context) error {
	id := c.FormValue("id")
	if id == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要修改的角色"})
	}

	name := c.FormValue("name")
	if name == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写角色名称"})
	}

	desc := c.FormValue("desc")
	if desc == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请填写角色描述"})
	}

	appId := c.FormValue("app_id")
	if appId == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择APP"})
	}

	role := make(map[string]interface{})
	role["name"] = name
	role["desc"] = desc
	role["app_id"] = appId
	role["update_time"] = time.Now().Unix()

	_, err := manager.UpdateRole(id, role)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// UpdateRolePremission
func UpdateRolePremission(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	id := c.QueryParam("id")
	if id == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞请选择要修改的角色😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	// 查询角色信息
	role, _ := manager.GetRoleById(id)
	if role.Id.Hex() == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞要修改的角色数据不存在😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	if role.App_id == "" {
		data := make(map[string]interface{})
		data["error_content"] = "😞请保证角色选择了APP😞"
		data["loginAdminInfo"] = loginAdminInfo
		data["env_desc"] = utils.GetEnvDesc()
		return c.Render(http.StatusOK, "error.html", data)
	}

	appsPermissions := getAppPremissions(role)

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["roleInfo"] = formatRole(role)
	data["app_premissions"] = appsPermissions
	data["loginAdminInfo"] = loginAdminInfo
	data["env_desc"] = utils.GetEnvDesc()

	return c.Render(http.StatusOK, "update_role_premission.html", data)
}

func DoUpdateRolePremission(c echo.Context) error {
	dataid := c.FormValue("id")
	if dataid == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要操作的角色"})
	}

	pids := c.FormValue("pids")

	pidsArray := strings.Split(pids, ",")
	if len(pidsArray) == 0 {
		return c.JSON(http.StatusOK, entity.Response{En: 403, Em: "请选择角色权限"})
	}

	role := make(map[string]interface{})
	role["premissions"] = pidsArray
	role["update_time"] = time.Now().Unix()

	_, err := manager.UpdateRole(dataid, role)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// DoDeleteRole
func DoDeleteRole(c echo.Context) error {
	dataid := c.FormValue("id")

	if dataid == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要删除的角色"})
	}

	// 判断角色是否存在
	role, err := manager.GetRoleById(dataid)
	if err != nil {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}
	if role.Id.Hex() != dataid {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
	}

	// 物理删除角色
	b, err := manager.DeleteRole(dataid)
	if b == false {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// DoDeleteRoleBatch
func DoDeleteRoleBatch(c echo.Context) error {
	dataids := c.FormValue("ids")

	if dataids == "" {
		return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "请选择要删除的角色"})
	}

	dataidsArray := strings.Split(dataids, ",")

	for _, dataid := range dataidsArray {
		// 判断角色是否存在
		role, err := manager.GetRoleById(dataid)
		if err != nil {
			return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
		}
		if role.Id.Hex() != dataid {
			return c.JSON(http.StatusOK, entity.Response{En: 402, Em: "数据错误"})
		}

		// 物理删除角色
		b, err := manager.DeleteRole(dataid)
		if b == false {
			return c.JSON(http.StatusOK, entity.Response{En: 402, Em: err.Error()})
		}
	}

	return c.JSON(http.StatusOK, entity.Response{En: 200, Em: "成功"})
}

// RoleList
func RoleList(c echo.Context) error {
	loginAdminInfo := manager.GetLoginAdminInfo(&c)

	id := c.QueryParam("id")
	name := c.QueryParam("name")

	skip, page := utils.GetSkipPage(utils.PageCount, c)

	// 查询模板列表
	count, _ := manager.GetRoleCount(id, name)
	roles, _ := manager.GetRoleList(id, name, skip, utils.PageCount)

	var roleList []map[string]interface{}
	for _, row := range roles {
		item := formatRole(row)
		roleList = append(roleList, item)
	}

	res := utils.Paginator(page, utils.PageCount, count)

	linkPrefix, query := getRoleLinkPrefixQuery("/roleList?", id, name)

	// 渲染结果到模板
	data := make(map[string]interface{})
	data["roleList"] = roleList
	data["paginator"] = res
	data["linkPrefix"] = linkPrefix
	data["total"] = count
	data["loginAdminInfo"] = loginAdminInfo
	data["query"] = query
	data["env_desc"] = utils.GetEnvDesc()
	return c.Render(http.StatusOK, "role_list.html", data)
}

func formatRole(row model.Role) map[string]interface{} {
	item := make(map[string]interface{})

	// 取App名称
	appName := ""
	if row.App_id != "" {
		app, _, err := manager.GetAppById(row.App_id)
		if err == nil && app.Id.Hex() != "" {
			appName = app.App_name
		}
	}

	// 取创建人姓名
	admin, _, _ := manager.GetAdminById(row.Adminid)
	adminName := ""
	if admin.Id.Hex() != "" {
		adminName = admin.Name
	}

	item["id"] = row.Id.Hex()
	item["name"] = row.Name
	item["desc"] = row.Desc
	item["premissions"] = row.Premissions
	item["app_id"] = row.App_id
	item["app_name"] = appName
	item["adminid"] = row.Adminid
	item["admin_name"] = adminName
	item["create_date"] = time.Unix(row.Create_time, 0).Format("2006-01-02 15:04:05")
	item["update_date"] = time.Unix(row.Update_time, 0).Format("2006-01-02 15:04:05")
	return item
}

func getRoleLinkPrefixQuery(linkPrefix string, id string, name string) (string, map[string]interface{}) {
	query := make(map[string]interface{})
	if id != "" {
		query["id"] = id
		linkPrefix += fmt.Sprintf("id=%s&", id)
	}
	if name != "" {
		query["name"] = name
		linkPrefix += fmt.Sprintf("name=%s&", name)
	}

	return linkPrefix, query
}

func getAppPremissions(role model.Role) map[string]interface{} {
	appId := role.App_id
	premissionIds := role.Premissions

	row, _, _ := manager.GetAppById(appId)
	appName := row.App_name
	premissions, _ := manager.GetAllPremissionByAppId(appId)

	plen := len(premissions)
	var premissionList = make([]map[string]interface{}, plen)
	index := 0
	for _, premission := range premissions {
		pid := premission.Id.Hex()
		item := make(map[string]interface{})
		item["id"] = pid
		item["key"] = premission.Key
		item["name"] = premission.Name
		item["is_select"] = false
		for _, tid := range premissionIds {
			if tid == pid {
				item["is_select"] = true
			}
		}
		premissionList[index] = item
		index++
	}

	appPremissions := make(map[string]interface{})
	appPremissions["app_id"] = appId
	appPremissions["app_name"] = appName
	appPremissions["premissions"] = premissionList

	return appPremissions
}
